import { produce } from 'immer';
import { v4 as uuidV4 } from 'uuid';
import type { Effect, ImmerReducer } from 'umi';
import cubes, { groupCubes, pageSetting } from '@/pages/tool/Decoration/editor/components';
import { cloneDeep, isEmpty, isFunction, keyBy, keys } from 'lodash';
import { message } from 'antd';
import { getPageById, saveOrUpdate, getTplById } from '@/services/decoration.service';
// import { querypullDownList } from '@/services/management.service';
// import { previewData } from '@/services/management.service';
// import { currentCubeBoolean } from '@/utils/calculate.util';

export type TDecorationModel = {
  namespace: 'decoration';
  state: TDecorationModelState;
  effects: {
    [key in string]: Effect;
  };
  reducers: {
    [key in string]: ImmerReducer<TDecorationModelState>;
  };
};

export type TDecorationModelState = typeof initialState;

export type PreviewCube = (typeof cubes)[number] & Record<'id', string>;

export type ErrorMsg = {
  [k in PreviewCube['id']]: string[];
} & Record<'page', string[]>;

const initialState = {
  // 页面参数
  pageParam: {
    name: '',
    type: 1,
    channelCode: '',
    // 0：草稿 2：已发布 3：使用中 4：定时发布
    status: 0,
  },
  loading: false,
  previewCode: '',
  // 分组组件
  groupCubes,
  // 所有组件
  cubes,
  cubesMap: keyBy(cubes, 'type'),
  // 已选的组件
  preview: [] as PreviewCube[],
  // 当前编辑的组件id
  activeSortItemId: '',
  // 页面设置
  pageSetting: pageSetting.default,
  // 错误
  errorMap: {} as ErrorMsg,
  // 只有页面设置时候有效 展示所有组件
  showPreViewItems: true,
  // 商品数据
  goodsList: [],
};

export const validateFn = async (cube: TDecorationModelState['pageSetting'] | PreviewCube) => {
  const { validate, initialValues } = cube;
  if (isFunction(validate)) {
    const res = await validate(initialValues);
    return res?.errors?.filter(Boolean);
  }
  return [];
};

const DecorationModel: TDecorationModel = {
  namespace: 'decoration',
  state: initialState,
  effects: {
    *validateUpdate(_, { call, put, select }) {
      const {
        activeSortItemId,
        preview,
        errorMap,
        pageSetting: pageSettings,
      } = yield select(({ decoration }: { decoration: TDecorationModelState }) => decoration);
      if (isEmpty(errorMap) || isEmpty(errorMap[activeSortItemId || 'page'])) {
        return;
      }
      let current = pageSettings;
      if (activeSortItemId) {
        current = preview.find((cube: PreviewCube) => cube.id === activeSortItemId);
      }
      if (!current) {
        return;
      }
      try {
        // @ts-ignore
        const res = yield call(validateFn, current);
        if (isEmpty(res)) {
          yield put({
            type: 'removeError',
            payload: {
              id: activeSortItemId || 'page',
            },
          });
        }
      } catch (error) {
        console.log(error);
      }
    },
    *save({ payload }, { call, select, put }) {
      yield put({
        type: 'updateLoading',
        payload: true,
      });

      const {
        preview,
        errorMap,
        pageSetting: pageSettings,
        pageParam,
      } = yield select(({ decoration }: { decoration: TDecorationModelState }) => decoration);
      if (!payload.isDraft && !isEmpty(errorMap)) {
        message.error('部分组件或者页面配置存在数据缺失, 请解决后再提交!');
        yield put({
          type: 'updateLoading',
          payload: false,
        });
        return;
      }
      const components = preview.map((cube: PreviewCube) => {
        const { type, initialValues, id } = cube;
        return {
          id,
          type,
          ...initialValues,
        };
      });
      const { initialValues } = pageSettings;
      const result = {
        ...pageParam,
        id: pageParam.id === '0' ? '' : pageParam.id,
        copy: 0,
        status: payload.isDraft ? 0 : 2,
        pageData: {
          components,
          ...initialValues,
        },
      };
      console.log(result, 'result');
      try {
        const { code, data, message: msg } = yield call(saveOrUpdate, result);
        if (code === 0) {
          message.success('数据保存成功!');
          // yield put({
          //   type: 'initSkuData',
          //   payload: {
          //     orgSkuData: data,
          //   },
          // });
        } else {
          message.error(msg);
        }
      } catch (error) {
        message.error('数据保存失败!');
      }
      yield put({
        type: 'updateLoading',
        payload: false,
      });
    },

    // 预览start
    *preview({ payload }, { call, select, put }) {
      yield put({
        type: 'updateLoading',
        payload: true,
      });
      const { preview, pageSetting: pageSettings } = yield select(
        ({ decoration }: { decoration: TDecorationModelState }) => decoration,
      );
      const components = preview.map((cube: PreviewCube) => {
        const { type, initialValues, id } = cube;
        return {
          id,
          type,
          ...initialValues,
        };
      });
      const { initialValues } = pageSettings;
      const pageData = {
        components,
        ...initialValues,
      };
      try {
        // const { code, data, message: msg } = yield call(previewData, { pageData });
        // if (code === 0) {
        //   // message.success('数据保存成功!');
        //   yield put({
        //     type: 'previewCodeUpdate',
        //     payload: data,
        //   });
        // } else {
        //   message.error(msg);
        // }
      } catch (error) {
        message.error('数据保存失败!');
      }
      yield put({
        type: 'updateLoading',
        payload: false,
      });
    },
    // 预览end

    *getTplData({ payload }, { call, select, put }) {
      yield put({
        type: 'updateLoading',
        payload: true,
      });
      try {
        const { code, data, message: msg } = yield call(getTplById, { id: payload });
        if (code === 0) {
          console.log(data, 'data');
          const { pageData, name, channelCode, id, type, status } = data;
          const json = JSON.parse(pageData);
          yield put({
            type: 'updatePageParam',
            payload: {
              name,
              channelCode,
              id,
              type,
              status,
            },
          });
          yield put({
            type: 'pageDataToPreview',
            payload: json,
          });
        } else {
          message.error(msg);
        }
      } catch (error) {
        message.error('数据查询失败!');
      }
      yield put({
        type: 'updateLoading',
        payload: false,
      });
    },

    *getPageData({ payload }, { call, select, put }) {
      yield put({
        type: 'updateLoading',
        payload: true,
      });
      try {
        const { code, data, message: msg } = yield call(getPageById, { id: payload.id });
        if (code === 0) {
          const { pageData, name, channelCode, id, type, status } = data;
          const json = JSON.parse(pageData);
          console.log(json);

          yield put({
            type: 'updatePageParam',
            payload: {
              name,
              channelCode,
              id,
              type,
              status,
            },
          });
          yield put({
            type: 'pageDataToPreview',
            payload: !payload.channelCode || payload.channelCode === channelCode ? json : {},
          });
        } else {
          message.error(msg);
        }
      } catch (error) {
        message.error('数据查询失败!');
      }
      yield put({
        type: 'updateLoading',
        payload: false,
      });
    },

    *getGoodsData({ payload }, { call, select, put }) {
      yield put({
        type: 'updateLoading',
        payload: true,
      });
      try {
        // const { code, data, message: msg } = yield call(querypullDownList, { type: 0 });
        // if (code === 0) {
        //   yield put({
        //     type: 'setGoodsList',
        //     payload: data || [],
        //   });
        // } else {
        //   message.error(msg);
        // }
      } catch (error) {
        message.error('数据查询失败!');
      }
      yield put({
        type: 'updateLoading',
        payload: false,
      });
    },
  },
  reducers: {
    addCube: (state, { payload }) =>
      produce(state, (draft) => {
        // if (!currentCubeBoolean(payload.type, state.preview, state.cubes)) return;
        const { type, addedIndex } = payload;
        if (!type) return;

        const current = draft.cubes.find((cube) => cube.type === type);

        if (!current) return;
        const id = uuidV4();
        const newCube = {
          id,
          ...current,
        };
        draft.preview.splice(addedIndex, 0, newCube);
        draft.activeSortItemId = id;
      }),

    deleteCube: (state, { payload }) =>
      produce(state, (draft) => {
        const { index } = payload;
        const [current] = draft.preview.splice(index, 1);
        if (current.id === draft.activeSortItemId) {
          draft.activeSortItemId = '';
        }
      }),

    copyCube: (state, { payload }) =>
      produce(state, (draft) => {
        const { index } = payload;
        const current = draft.preview[index];
        // if (!currentCubeBoolean(current.type, state.preview, state.cubes)) return;
        if (!current) return;
        const newCube = cloneDeep(current);
        newCube.id = uuidV4();
        draft.preview.splice(index + 1, 0, newCube);
      }),

    sortPreview: (state, { payload }) =>
      produce(state, (draft) => {
        const { removedIndex, addedIndex } = payload;
        if (!draft.preview.length) return;
        const [current] = draft.preview.splice(removedIndex, 1);
        draft.preview.splice(addedIndex, 0, current);
      }),

    setActiveSortItemId: (state, { payload }) =>
      produce(state, (draft) => {
        const { id } = payload;
        draft.activeSortItemId = id || '';
      }),

    updateData: (state, { payload }) =>
      produce(state, (draft) => {
        draft.preview.forEach((p) => {
          if (p.id === draft.activeSortItemId) {
            p.initialValues = {
              ...p.initialValues,
              ...payload,
            };
          }
        });
      }),

    updatePageSetting: (state, { payload }) =>
      produce(state, (draft) => {
        draft.pageSetting.initialValues = {
          ...draft.pageSetting.initialValues,
          ...payload,
        };
      }),

    setErrorMap: (state, { payload }) =>
      produce(state, (draft) => {
        draft.errorMap = {
          ...payload,
        };
        if (payload.page) {
          draft.activeSortItemId = '';
        } else {
          draft.activeSortItemId = keys(payload)[0] || '';
        }
      }),

    removeError: (state, { payload }) =>
      produce(state, (draft) => {
        delete draft.errorMap[payload.id];
      }),

    updateLoading: (state, { payload }) =>
      produce(state, (draft) => {
        draft.loading = payload;
      }),

    previewCodeUpdate: (state, { payload }) =>
      produce(state, (draft) => {
        draft.previewCode = payload;
      }),

    updatePageParam: (state, { payload }) =>
      produce(state, (draft) => {
        draft.pageParam = {
          ...draft.pageParam,
          ...payload,
        };
      }),

    pageDataToPreview: (state, { payload }) =>
      produce(state, (draft) => {
        const { components, ...rest } = payload;
        draft.pageSetting.initialValues = {
          ...rest,
        };
        draft.preview = components
          .map((item: any) => {
            const initCube = draft.cubesMap[item.type];
            if (!initCube) return null;
            const { id, type, ...rest2 } = item;
            return {
              ...draft.cubesMap[item.type],
              initialValues: rest2,
              id,
              type,
            };
          })
          .filter(Boolean);
      }),
    setShowPreViewItems: (state, { payload }) =>
      produce(state, (draft) => {
        draft.showPreViewItems = payload;
      }),

    setGoodsList: (state, { payload }) =>
      produce(state, (draft) => {
        draft.goodsList = payload;
      }),
  },
};

export default DecorationModel;
